﻿#include "mixdevice.h"
#include <QDebug>
#include "../commons/configfile.h"
#include "../commons/blowairpins.h"
#include "../logs/printlogs.h"
MixDevice * MixDevice::m_mixDevice=NULL;
MixDevice::MixDevice(QObject *parent) : QObject(parent)
  , m_serial(NULL)
  , m_comAlgor(NULL)
  , m_timer(NULL)
  , m_sendtimer(NULL)
  , m_isHandlCmds(false)
{
    m_comAlgor = new ComAlgor();
    m_serial = new QSerialPort();
    connect(m_serial,SIGNAL( readyRead() ),this,SLOT( onDataReceived() ));

    m_timer = new QTimer();
    connect(m_timer,SIGNAL( timeout() ),this,SLOT( onTimeOut() ));
    m_sendtimer = new QTimer();
    connect(m_sendtimer,SIGNAL( timeout() ),this,SLOT( onSendTimeOut() ));

    m_closetimer= new QTimer();
    connect(m_closetimer,SIGNAL( timeout() ),this,SLOT( onCloseTimeOut() ));

    m_runtimer = new QTimer();
    connect(m_runtimer,SIGNAL( timeout() ),this,SLOT( onRunTimeOut() ));

    QList<int> lista = BlowairPins::gestance()->keyPins();

    for(int i =0; i < lista.size() ;i++){
        m_pinsMap.insert(lista.at(i),0);
        m_cmdPins.insert(lista.at(i),0);
    }
    initComSeriel();
    m_cmdIndexs = m_cmdPins.firstKey();
    if(m_runtimer != NULL){
        m_runtimer->start(20);
    }
}

MixDevice::~MixDevice()
{

}

MixDevice *MixDevice::gestance()
{

    if(m_mixDevice == NULL){

        m_mixDevice = new MixDevice();

    }

    return m_mixDevice;
}

void MixDevice::initComSeriel()
{
    QString names =  ConfigFile::gestance()->getCom4Name();
#ifdef DEBUG_INFOR
    qDebug()<<"names=="<<names;
#endif
    if(names.length() > 0){
#ifdef DEBUG_INFOR
        qDebug()<<__func__<<__LINE__;
#endif

        QSerialPortInfo info(names);
        m_serial->setPortName(names);
        qDebug()<<__func__<<__LINE__<<"PortName=="<<names;
        m_serial->setBaudRate(QSerialPort::Baud38400);
        m_serial->setParity(QSerialPort::NoParity);
        m_serial->setDataBits(QSerialPort::Data8);
        m_serial->setStopBits(QSerialPort::OneStop);
        m_serial->setFlowControl(QSerialPort::NoFlowControl);

        if(m_serial->open(QIODevice::ReadWrite)) // 以读写方式打开串口
        {
#ifdef DEBUG_INFOR
            qDebug()<<__func__<<__LINE__;
#endif

            closeLanes(12,5);
        }
#ifdef DEBUG_INFOR
        qDebug()<<__func__<<__LINE__;
#endif

    }

}

void MixDevice::openLanes(int start, int nums)
{
#ifdef DEBUG_LOG_INFOR
    QString printlogStr=typeid(this).name()+QString(" %1").arg( __func__) +" -- "+ QString("%1").arg( __LINE__) + QString("%1").arg(start)+"=" + QString("%1").arg(nums) ;
    PrintLogb::gestance()->printInfor(printlogStr);
#endif
    uint8_t address_pos = 0x01;
    uint8_t ch[100];
    uint8_t tempa;
    uint32_t lens = 0;
    uint16_t check_crc=0;
    ch[0]= address_pos ;
    ch[1]=0x10;
    ch[2]=0x00;
    ch[3]=(uint8_t)(start -1);
    ch[4]=0x00;
    ch[5]=(uint8_t)nums;
    ch[6]=(uint8_t)nums * 2;


    lens = 7;
    for(int i = 0; i < nums ; i++,lens+=2){
        ch[7 + i*2 ]=0x00;
        ch[8 + i*2 ]=0x01;

    }

    check_crc=m_comAlgor->crcVal(ch,lens);

    tempa =(uint8_t)(check_crc) ;
    ch[lens]=tempa;


    lens++;
    tempa =(uint8_t)(check_crc>>8);
    ch[lens]=tempa;

    lens++;
    QByteArray by((char * )ch,lens);
#ifdef DEBUG_INFOR
    qDebug()<<__func__<<__LINE__<<by.toHex();
#endif
    if(m_serial != NULL){
        m_serial->write(by);
        m_serial->flush();
    }
}

void MixDevice::handlSingLanes(int start, int nums)
{
#ifdef DEBUG_LOG_INFOR
    QString printlogStr=typeid(this).name()+QString(" %1").arg( __func__) +" -- "+ QString("%1").arg( __LINE__) + QString("%1").arg(start)+"=" + QString("%1").arg(nums) ;
    PrintLogb::gestance()->printInfor(printlogStr);
#endif
    uint8_t address_pos = 0x02;
    uint8_t ch[100];
    uint8_t tempa;
    uint32_t lens = 0;
    uint16_t check_crc=0;
    ch[0]= address_pos ;
    ch[1]=0x05;
    ch[2]=0x00;
    ch[3]=0x00;
    ch[4]=(uint8_t)0xFF;
    ch[5]=0x00;


    lens = 6;
    check_crc=m_comAlgor->crcVal(ch,lens);

    tempa =(uint8_t)(check_crc) ;
    ch[lens]=tempa;


    lens++;
    tempa =(uint8_t)(check_crc>>8);
    ch[lens]=tempa;

    lens++;
    QByteArray by((char * )ch,lens);
#ifdef DEBUG_INFOR
    qDebug()<<__func__<<__LINE__<<by.toHex();
#endif
    if(m_serial != NULL){
        m_serial->write(by);
        m_serial->flush();
    }
}

void MixDevice::openPins(int pins, int times)
{
#ifdef DEBUG_LOG_INFOR
    QString printlogStr=typeid(this).name()+QString(" %1").arg( __func__) +" -- "+ QString("%1").arg( __LINE__)  ;
    PrintLogb::gestance()->printInfor(printlogStr);
#endif
    m_sendCmd.insert(pins,times);
    if(m_sendtimer != NULL ){
        m_sendtimer->stop();
    }

    if(m_sendCmd.size() > 0){

        if(m_sendtimer != NULL ){
            m_sendtimer->start(20);
        }
    }
}

void MixDevice::handlCmdPins(QByteArray infors)
{
#ifdef DEBUG_LOG_INFOR
    QString printlogStr=typeid(this).name()+QString(" %1").arg( __func__) +" -- "+ QString("%1").arg( __LINE__) + QString("%1").arg(QString(infors)) ;
    PrintLogb::gestance()->printInfor(printlogStr);
#endif
    m_cmdPins.clear();
    for(int i = 0; i< infors.size() ; i+=2){
        int pins = infors.at(i);
        int status = infors.at(i+1);
        m_cmdPins.insert(pins,status);
    }
#ifdef DEBUG_INFOR
    qDebug()<<__func__<<__LINE__<<m_cmdPins;
#endif
    if(m_cmdPins.size() > 0){
        m_isHandlCmds = true;
        m_cmdIndexs = m_cmdPins.firstKey();
        if(m_runtimer != NULL){
            m_runtimer->start(20);
        }
    }
}

void MixDevice::openCmdPins(int pins)
{
#ifdef DEBUG_LOG_INFOR
    QString printlogStr=typeid(this).name()+QString(" %1").arg( __func__) +" -- "+ QString("%1").arg( __LINE__)+"="+QString(pins)  ;
    PrintLogb::gestance()->printInfor(printlogStr);
#endif
    m_cmdPins.insert(pins,1);
    if(m_cmdPins.size() > 0){
        m_isHandlCmds = true;
        m_cmdIndexs = m_cmdPins.firstKey();
        if(m_runtimer != NULL){
            m_runtimer->start(20);
        }
    }


}

void MixDevice::closeCmdPins(int pins)
{
#ifdef DEBUG_LOG_INFOR
    QString printlogStr=typeid(this).name()+QString(" %1").arg( __func__) +" -- "+ QString("%1").arg( __LINE__)+"="+QString(pins)  ;
    PrintLogb::gestance()->printInfor(printlogStr);
#endif
    m_cmdPins.insert(pins,0);
    if(m_cmdPins.size() > 0){
        m_isHandlCmds = true;
        m_cmdIndexs = m_cmdPins.firstKey();
        if(m_runtimer != NULL){
            m_runtimer->start(20);
        }
    }
}

void MixDevice::handlPins()
{

}

void MixDevice::closeLanes(int start, int nums)
{
#ifdef DEBUG_LOG_INFOR
    QString printlogStr=typeid(this).name()+QString(" %1").arg( __func__) +" -- "+ QString("%1").arg( __LINE__) + QString("%1").arg(start)+"=" + QString("%1").arg(nums) ;
    PrintLogb::gestance()->printInfor(printlogStr);
#endif
    uint8_t address_pos = 0x01;
    uint8_t ch[100];
    uint8_t tempa;
    uint32_t lens = 0;
    uint16_t check_crc=0;
    ch[0]= address_pos ;
    ch[1]=0x10;
    ch[2]=0x00;
    ch[3]=(uint8_t)(start -1);
    ch[4]=0x00;
    ch[5]=(uint8_t)nums;
    ch[6]=(uint8_t)nums * 2;


    lens = 7;
    for(int i = 0; i < nums ; i++,lens+=2){
        ch[7 + i*2 ]=0x00;
        ch[8 + i*2 ]=0x00;

    }

    check_crc=m_comAlgor->crcVal(ch,lens);

    tempa =(uint8_t)(check_crc) ;
    ch[lens]=tempa;


    lens++;
    tempa =(uint8_t)(check_crc>>8);
    ch[lens]=tempa;

    lens++;
    QByteArray by((char * )ch,lens);
#ifdef DEBUG_INFOR
    qDebug()<<__func__<<__LINE__<<by.toHex();
#endif
    if(m_serial != NULL){
        m_serial->write(by);
        m_serial->flush();
    }
}

void MixDevice::onDataReceived()
{

    if(m_serial != NULL){

        uint8_t cha[2];
        cha[0]=0x01;
        cha[1]=0x10;

        QByteArray data = m_serial->readAll();
        m_currentData+=data;
#ifdef DEBUG_INFOR
        qDebug()<<__func__<<__LINE__<<"data=="<<data.toHex();
#endif
        if(m_currentData.size() >= 8){
            QByteArray jusit((char *)cha,2);
            int indexa = m_currentData.indexOf(jusit);
            if(indexa >= 0){

            }

            m_currentData.clear();
        }

    }

}

void MixDevice::onSendTimeOut()
{
    QList<int> keys = m_sendCmd.keys();
    if(keys.size() > 0){
        int pins = keys.at(0);
        openLanes(pins , 1);
        qint64 times = m_sendCmd.value(pins);
        m_sendCmd.remove(pins);
        qint64 linas =  QDateTime::currentMSecsSinceEpoch();
        m_runPins.insert(pins,linas +times);

    }
    if(m_sendCmd.size() > 0){
        m_sendtimer->start(20);
    }
    if(m_runPins.size() > 0){
        m_timer->stop();
        m_timer->start(20);
    }

}

void MixDevice::onTimeOut()
{
    if(m_timer != NULL ){
        m_timer->stop();
    }
    qint64 linas =  QDateTime::currentMSecsSinceEpoch();
    QList<int> lista = m_runPins.keys();
    QList<int> listb;
    for(int i = 0;i < lista.size() ; i++){
        int pina = lista.at(i);
        qint64 timb = m_runPins.value(pina);
        if(linas >= timb){
            listb.append(pina);
        }
    }
    if(listb.size() > 0){
        for(int i = 0;i < listb.size() ; i++){
            int pina = listb.at(i);
            m_closeList.append(pina);
            m_runPins.remove(pina);
        }
    }

    if(m_closetimer != NULL ){
        m_closetimer->stop();
    }

    if(m_closeList.size() > 0){

        if(m_closetimer != NULL ){
            m_closetimer->start(20);
        }
    }

    if(m_runPins.size() > 0){

        if(m_timer != NULL ){
            m_timer->start(20);
        }
    }else{
        if(m_closeList.size() <= 0){

        }
    }
}

void MixDevice::onCloseTimeOut()
{
    if(m_closetimer != NULL ){
        m_closetimer->stop();
    }
    if(m_closeList.size() > 0){
        int pins =m_closeList.at(0);
        m_closeList.pop_front();
        closeLanes(pins , 1);
    }
    if(m_closeList.size() > 0){

        if(m_closetimer != NULL ){
            m_closetimer->start(20);
        }
    }else{

    }
}

void MixDevice::onRunTimeOut()
{
    if(m_runtimer != NULL){
        m_runtimer->stop();
    }
    int status = m_cmdPins.value(m_cmdIndexs);

    int pins = m_cmdIndexs;// BlowairPins::gestance()->getRealPin(m_cmdIndexs);

    if(status == 1){
        openLanes(pins,1);
        m_cmdPins.insert(m_cmdIndexs,1);
    }else{
        closeLanes(pins,1);
        m_cmdPins.insert(m_cmdIndexs,0);
    }

    m_cmdPins.remove(m_cmdIndexs);
    if(m_cmdPins.size() > 0){
        m_cmdIndexs = m_cmdPins.firstKey();
        if(m_runtimer != NULL){
            m_runtimer->start(20);
        }
    }else{
        if(m_isHandlCmds){

            //  emit sigMixDeviceSuccess();

        }
        m_isHandlCmds = false;
    }

}
